#include <iostream>
#include <bitset>
#include <unistd.h>
#include <string>
#include "base_test.h"
#include <utility>
#include <vector>
#include <functional>
#include <string.h>
#include <memory>
#include "map_assign.h"
#include <vector>
#include "dbg.h"
#include "keyword_filter.h"
#include "MyAlgorithm.h"
#include "template_test.h"
#include "openmp_test.h"
#include "call_python.h"
#include "buffer_test.h"

typedef std::function<void(void)> Fun;

void is_r_value(int &&)
{
    std::cout<<"is right value"<<std::endl;
}
void is_r_value(const int&)
{
    std::cout<<"is left value"<<std::endl;
}

class Base
{
    public:
        Base(){}
        virtual ~Base(){}
    private:
        char* buf;
};

class Num
{
    public:
    Num()
    {
        std::cout<<"Num()"<<std::endl;
    }
    Num(const Num& )
    {
        std::cout<<"Num(111)"<<std::endl;
    }
    ~Num()
    {
        std::cout<<"~Num()"<<std::endl;
    }
    Num& operator =(const Num& other)
    {
        std::cout<<"operator="<<std::endl;
        memcpy((void*)bs,(void*)other.bs,sizeof(Base));
        return *this;
    }
    virtual void Do(){};
    private:
    int a;
    char b;
    std::string c;
    char* buf;
    Base* bs;
};

template< class C >
class call_push_back
{
    C& c_;
    public:
    call_push_back( C& c ) : c_( c )
    { }

    template< class T >
        void operator()( T r ) 
        {
            c_.push_back( r );
        }
};

template<typename Fun>
class ListInserter
{
    public:
        ListInserter(Fun f):insert_(f)
    {
    }
        template<class T>
            ListInserter& operator,(const T& t)
            {
                RUNTIME
                insert_(t);
                return *this;
            }
        template<class T>
            ListInserter& operator()(const T& t)
            {
                insert_(t);
                return *this;
            }

    private:
        Fun  insert_;
};

template< class Function >
ListInserter< Function >
make_list_inserter( Function fun )
{
    return ListInserter< Function >( fun );
}

template<class T,class A>
ListInserter<call_push_back<std::vector<T,A>>>
operator+=(std::vector<T,A>& c,T v)
{
    auto  insert = make_list_inserter(call_push_back<std::vector<T,A>>(c));
    insert(v);
    return insert;
}
Num GetNum(){Num a;return std::move(a);}

void intToByte(int i,char *bytes,int size = 4)
{
    memset(bytes,0,sizeof(char) * size);
    bytes[0] = (char) (0xff & i);
    bytes[1] = (char) ((0xff00 & i) >> 8);
    bytes[2] = (char) ((0xff0000 & i) >> 16);
    bytes[3] = (char) ((0xff000000 & i) >> 24);
    return ;
}
int bytesToInt(char* bytes,int size = 4)
{
    int addr = bytes[0] & 0xFF;
    addr |= ((bytes[1] << 8) & 0xFF00);
    addr |= ((bytes[2] << 16) & 0xFF0000);
    addr |= ((bytes[3] << 24) & 0xFF000000);
    return addr;
}

int main()
{
    std::vector<int> vv;
    vv.reserve(10);
    vv[1] = 7;
    vv[7] = 10;


    for(int i = 0; i < 10;i++)
    {
        std::cout<<"vv:"<<vv[i]<<std::endl;
    }

    vv.reserve(20);

    vv[16] = 16;
    for(int i = 0; i < 20;i++)
    {
        std::cout<<"vv:"<<vv[i]<<std::endl;
    }

    std::cout<<"-----------------------------------"<<std::endl;


    RUNTIME
    std::bitset<32> bitvec(0xffff);
    bitvec.set(17);
    std::cout<<bitvec<<std::endl;
    sleep(1);

    dbg(bitvec);

    char buf[1024];
    intToByte(111,buf);

    std::cout<<(char)buf[0]<<(char)buf[1]<<(char)buf[2]<<(char)buf[3]<<std::endl;

    std::vector<int> v;
    v.assign(7,100);
    v += 111,22,33,44,55;

    for(auto i : v)
    {
        std::cout<<"i=:"<<i<<std::endl;
    }

    Num&& a  = GetNum();
//    is_r_value(std::move(a));
    int b = 100;
    is_r_value(b);
    Fun cb;
    cb = [](){std::cout<<"ffff<"<<std::endl;};
    if(!cb)
    {
        std::cout<<"cb is empty"<<std::endl;
    }
    else
    {
        cb();
    }



    std::unique_ptr<int> pInt = nullptr;
    pInt = std::unique_ptr<int>(new int(5));

    std::cout<<bitvec.to_ulong()<<"\t"<<*pInt<<std::endl;
    /* 
    Assign::Test tests;
    tests.Run();
    */

    FilterOper keyOpt;
    keyOpt.Load("key.txt");
    std::string words = "我是你爹，shabi fuck you ,fuck 你妈， 傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile我是你爹，shabi fuck you ,傻逼，草泥马，你是狗杂种 ni mamasile长得跟前列腺似的，尿尿都分叉了，赶快去治治吧！人贱一辈子，猪贱一刀子，活着浪费空气，死了浪费土地，在家浪费RMB！";
    std::cout<<"length:"<<words.size()<<std::endl;
    //auto keyb = keyOpt("i am fine fuck you,you are bitch,hhhhhhhh fuck you hhhhhhhhh bitch heihei");
    auto keyb = keyOpt(words.c_str());
    if(keyb)
    {
        std::cout<<"find"<<std::endl;
    }
    else
    {
        std::cout<<"NO find"<<std::endl;
    }
    keyOpt.Show();
    std::cout<<"-----------------------------------------------------"<<std::endl;
    FilterOper2rd keyOpt2;
    keyOpt2.Load("key.txt");
    keyOpt2(words.c_str());
    keyOpt2.Show();
    AlgorithmTest::Test();
    uint32_t id = 1;

    uint64_t uid = (uint64_t)id<<32;
    std::cout<<"1<<32="<< uid<<" id="<<id<<std::endl;

    SystemTest sys;
    sys.Show();

    OpenMp op;
    op.test();
    CallPython cpy;
    cpy.Test();
    BufferTest::Test();

    return 0;
}
